/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jku.semtech.sparql;

import jku.semtech.common.Player;
import jku.semtech.common.Team;
import jku.semtech.rdf.TeamRDF;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP;

public class DBPediaCrawler {

	private TeamRDF rdf;

	public DBPediaCrawler(TeamRDF trdf) {

		this.rdf = trdf;
		loadModel();
	}

	// get Info for Player from dbpedia.org
	public void loadModel() {
		ResultSet rs = null;
		for (Team team : rdf.getTeams().values()) {
			for (Player player : team.getPlayers().values()) {
				do {
					System.out.println("try to fetch player: "
							+ player.getDbpediaID());
					rs = fetchPlayer(player.getDbpediaID());
				} while (rs == null);

				updatePlayer(player, rs);
				rs = null;
			}
		}
	}

	private ResultSet fetchPlayer(String playerID) {
		System.out.println("fetchPlayer( " + playerID + ")");

		try {
			/* String queryStr = "prefix player:<http://dbpedia.org/resource/>"
					+ "prefix player-de:<http://de.dbpedia.org/resource/>"
					+ "prefix dbpedia-owl:<http://dbpedia.org/ontology/>"
					+ "prefix dbpprop:<http://dbpedia.org/property/>"
					+ "prefix rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>"
					+ "prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#>"
					+ "prefix dbpprop-de:<http://de.dbpedia.org/property/>"
					+ "prefix foaf:<http://xmlns.com/foaf/0.1/>"
					+

					"SELECT distinct ?abstract ?birthDate ?birthPlace ?clubName ?clubManagerName ?position ?picURL ?clubEntryYear ?goals "
					+ "WHERE {"
					+ "player:" + playerID
					+ " dbpedia-owl:abstract ?abstract FILTER (lang (?abstract) = 'de')."
					+ "player:" + playerID
					+ " dbpedia-owl:position ?position."
					+ "player:" + playerID
					+ " dbpprop:currentclub ?currentClub. "
					+ "?currentClub rdfs:label ?clubName FILTER (lang (?clubName) = 'de')."
					+ "?currentClub dbpedia-owl:manager ?clubManager. "
					+ "player:" + playerID
					+ " dbpedia-owl:birthDate ?birthDate. "
					// + "OPTIONAL { " + "player-de:" + playerID
					// + " dbpprop-de:geburtsland ?birthPlace. } "
					+ "player:" + playerID
					+ " foaf:depiction ?picURL. "
					+ "player:" + playerID
					+ " dbpprop:years ?clubEntryYear. "
					+ "player:" + playerID
					+ " dbpprop:goals ?goals. "
					+ "OPTIONAL { " + "player:" + playerID
					+ " dbpprop:birthPlace ?birthPlace. }} "; */
			
			String queryStr = "prefix player:<http://dbpedia.org/resource/>"
					+ "prefix dbpedia-owl:<http://dbpedia.org/ontology/>"
					+ "prefix dbpprop:<http://dbpedia.org/property/>"
					+ "prefix rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>"
					+ "prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#>"
					+ "prefix foaf:<http://xmlns.com/foaf/0.1/>"
					
					+ "SELECT distinct ?abstract ?birthDate ?birthPlace2 ?birthPlace ?clubName ?clubManagerName ?position ?picURL ?clubEntryYear ?goals "
					+ "WHERE {"
					+ "player:" + playerID + " dbpedia-owl:abstract ?abstract FILTER (lang (?abstract) = 'de')."
					+ "player:" + playerID + " dbpedia-owl:position ?position."
					+ "player:" + playerID + " dbpprop:currentclub ?currentClub. "
					+ "?currentClub rdfs:label ?clubName FILTER (lang (?clubName) = 'de')."
					+ "?currentClub dbpedia-owl:manager ?clubManager. "
					+ "player:" + playerID + " dbpedia-owl:birthDate ?birthDate. "
				
					+ "player:" + playerID + " foaf:depiction ?picURL. "
					+ "player:" + playerID + " dbpprop:years ?clubEntryYear. "
					+ "player:" + playerID + " dbpprop:goals ?goals. "
					
					+ "OPTIONAL {player:" + playerID + " dbpprop:birthPlace ?birthPlace. }"
					+ "OPTIONAL {?birthPlace rdfs:label ?birthPlace2 FILTER (lang (?birthPlace2) = 'de').} "
					+ "OPTIONAL {?clubManager dbpedia-owl:commonName ?clubManagerName. } "
					+ "} "
					+ "ORDER BY DESC(?goals + ?clubEntryYear) LIMIT 1";

			Query query = QueryFactory.create(queryStr);

			// Remote execution.
			QueryExecution qexec = QueryExecutionFactory.sparqlService(
					"http://dbpedia.org/sparql", query);
			// Set the DBpedia specific timeout.
			((QueryEngineHTTP) qexec).addParam("timeout", "10000");

			// Execute
			ResultSet temp = qexec.execSelect();

			//qexec.close();
			return temp;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("ERROR ERROR");
		}
		return null;
	}

	private void updatePlayer(Player player, ResultSet rs) {
		if (rs.hasNext()) {
			QuerySolution values = rs.next();
			
			while (rs.hasNext()) {
				values = rs.next();
			}

			for (String attribute : rs.getResultVars()) {
				switch (attribute) {
				case "abstract":
					player.setDescription(values.getLiteral(attribute)
							.getValue().toString());
					break;
				case "birthDate":
					if (values.get(attribute) == null) {
						player.setBirthDate("");
					} else {
						player.setBirthDate(values.getLiteral(attribute)
								.getValue().toString());
					}
					break;
				case "birthPlace":
					if (values.get(attribute) == null) {
						player.setBirthPlaceName("");
					} else {
						String temp = values.get(attribute).toString();
						int pos = temp.lastIndexOf("/") + 1;
						temp = temp.substring(pos);
						player.setBirthPlaceName(temp);
					}
					break;
				case "birthPlace2":
					if (values.get(attribute) == null) {
						//when null the earlier found birthPlace should be taken
					} else {
						player.setBirthPlaceName(values.getLiteral(attribute).getValue().toString());
					}
					break;
				case "clubName":
					player.setClubName(values.getLiteral(attribute).getValue()
							.toString());
					break;
				case "clubManagerName":
					if (values.get(attribute) == null) {
						player.setClubManagerName("");
					} else {
						player.setClubManagerName(values.getLiteral(attribute)
								.getValue().toString());
					}
					break;
				case "position":
					player.setRealFieldPosition(values.getLiteral(attribute)
							.getValue().toString());
					break;
				case "clubEntryYear":
					player.setClubEntryYear(values.getLiteral(attribute)
							.getValue().toString());
					break;
				case "picURL":
					player.setPicURL(values.get(attribute).toString());
					break;
				case "goals":
					player.setGoals(values.getLiteral(attribute).getValue().toString());
					break;
				}
			}
		}
	}
}
